<?php
/*
Plugin Name: Twit2RSS
Plugin URI: http://www.whitleymedia.com
Description: Read Twitter posts through your RSS reader.  Also generates a link blog from posts that contain links.  This is an enhanced RSS feed that offers more information and features than a standard Twitter feed.  Requires PHP 5.1 or greater. 
Version: 1.5
Author: Shannon Whitley
Author URI: http://www.voiceoftech.com/swhitley/

Copyright (C) 2008 Whitley Media

This program is free software; you can redistribute it and/or
modify it under the terms of version 2 of the GNU General Public
License as published by the Free Software Foundation.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details, available at
http://www.gnu.org/copyleft/gpl.html
or by writing to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

=================================================================
INSTRUCTIONS

1.  Update the $username, $password, and $secret below.  Enter your 
    Twitter username and password.
2.  In your feed reader, subscribe to either of the following links:

    RSS Feed:  	http://[WordPress Blog Home]?feed=twit2rss&secret=[secret] 
    Link Feed:  	http://[WordPress Blog Home]?feed=twit2rss&jtl=true 

The Link Feed will only be updated if the RSS or Link Feed are viewed.
To keep the Link Feed current, subscribe to the RSS feed in a feed reader.
The links will be updated everytime the feed reader polls the feed.

*/
//****************************************
//* Insert your Twitter Username
//* and Password
//* 
//* 
//* Example:
//*
//* $username='jdoe';
//* $password='mypswd123';
//* $secret='mysecret123';
//* 
//****************************************
$username='';
$password='';
$secret='';
//****************************************

//OPML Title
//Change this to alter your OPML Title.
$opml_title = 'Twitter Links';

//Links to keep, Default = 25
//Change this number to keep more links.
//Older links will be deleted.
$links_to_keep = 25;


//Group By screen name or date?
//Change this to false to group by date.
$group_by_screen_name = true;

// Set the default timezone to use. Available since PHP 5.1
// Change to your timezone or leave the default Universal Time setting.
//* Comment out this line if it produces a PHP error.
// Default = UTC
date_default_timezone_set('UTC');

//****************************************
//* Categorize your 'Friends'
//*
//* Include a line for any friends that 
//* you'd like to categorize.  You can 
//* categorize some friends and not others,
//* or you can skip this section.
//*
//* Add a separate line for each user
//* between the Start and End lines.
//*
//* Format:
//* @[user name]:[category]
//*
//* Example:
//*
//* @StartFriendList:Start
//* @BobJones:Friend
//* @JanCol:Acquaintance
//* @JimBob:Competitor
//* @EndFriendList:End
//*
//* Modify the list below:
//****************************************
$friend_list = '
@StartFriendList:Start
@EndFriendList:End
';
//****************************************
//* Stop!  Do not modify any more code.
//****************************************

$friends_temp = explode('@',$friend_list);
$friends = Array();
foreach($friends_temp as $temp)
{
    $tempvals = explode(':',$temp);
    if(count($tempvals) > 1)
    {
        $friends[$tempvals[0]] = $tempvals[1];
    }
}

//Create the jtl table.
register_activation_hook(__FILE__,'JTLInstall'); 

//Enable feed=twit2rss in querystring.
function do_feed_twit2rss()
{
	load_template(__FILE__); 
}

if($_GET['feed'] == "twit2rss")
{
    global $secret;

    if(!isset($_GET['jtl']))
    {
	    if(strlen($secret) > 0)
	    {
		if($_GET["secret"] != $secret)
		{
			wp_die("Incorrect secret.");
		}
	    }
	    else
	    {
		    wp_die("Secret is not set.");
	    }
    }

    $rss = twit2rss();
    header ("content-type: text/xml"); 
    if(!isset($_GET['jtl']))
    {
	    //Write RSS
    	   echo $rss;

    }
    else
    {
	   //Write OPML
    	   echo JTLOPML();
    }
}

function JTLOPML()
{
		global $wpdb, $opml_title, $group_by_screen_name, $links_to_keep;

		//Delete links over the limit.
		$keep_date = $wpdb->get_var("select created_at from ".$wpdb->prefix."jtl_links order by created_at desc limit ".$links_to_keep.",1");

		if($keep_date)
		{
			$wpdb->query("delete from ".$wpdb->prefix."jtl_links where created_at <= '".$keep_date."'");
		}


		$sql = "select link, name, screen_name, status, image, created_at, protected from ".$wpdb->prefix . "jtl_links ";
		if($group_by_screen_name)
 		{
			 $sql .= "order by screen_name, created_at desc ";
		}
		else
		{
			 $sql .= "order by created_at desc, screen_name ";
		}

		$rs = $wpdb->get_results($sql,ARRAY_A);
		


            $outline = false;
		$opml = '<?xml version="1.0" encoding="ISO-8859-1"?>'."\r\n";
		$opml .= '<opml version="1.0">'."\r\n";
		$opml .= '<head>'."\r\n";
		$opml .= '	<title>'.$opml_title.'</title>'."\r\n";
		$opml .='</head>'."\r\n";
		$opml .='<body>'."\r\n";
		if($rs)
            {
                $prev = "";
                foreach($rs as $row)
                {
			  //Don't show protected posts unless admin.
			  if($row["protected"] == "true" && !is_admin())
			  {
				continue;
			  }
			  if($group_by_screen_name)
			  {
				$current = $row["screen_name"];
			  }
			  else
			  {
				$current = date('d M Y', strtotime($row["created_at"]));
			  }
                    if($current != $prev)
                    {
				if($prev != "")
                        {
					$opml .= '</outline>'."\r\n";
                        }
				$prev = $current;
				$opml .= '<outline text="'.$current.'">'."\r\n";
                  	$outline = true;  
			  }
			  $oText = htmlspecialchars('<img src="'.$row["image"].'" border="0" width="24" style="margin-right:3px;"/>'.$row["screen_name"].' '.$row["status"].' <br/>'.date('D, d M Y g:i a e', strtotime($row["created_at"]))); 
			  $oUrl = htmlspecialchars($row["link"]);
			  $opml .= '<outline text="'.$oText.'"  type="link" url="'.$oUrl.'" dateCreated="'.date('D, d M Y g:i a e', strtotime($row["created_at"])).'"/>'."\r\n";
		    }
		if($outline)
		{
			$opml .= '</outline>'."\r\n";
		}

		}
		$opml .='</body></opml> '."\r\n";

		return $opml;


}

function twit2rss()
{

    global $username, $password, $friends;

    //GET the Twitter Statuses
    $curl = new CURL();
    $curl->username = $username;
    $curl->password = $password;
    $xml = $curl->get("http://twitter.com/statuses/friends_timeline.xml");
    //$xml = $curl->get("http://twitter.com/statuses/user_timeline.xml");


    //Load the XML file
    $doc = new DOMDocument();
    $doc->loadXML($xml);

    //Status Nodes
    $nodeList = $doc->getElementsByTagName('status');

    if($nodeList->length == 0)
    {
        //Twitter Error
        $nodeList = $doc->getElementsByTagName('error');
        if($nodeList.length != 0)
        {
            die($nodeList[0]->nodeValue);
        }
    }
    else
    {
	    //RSS Begin
	    $rss = '<?xml version="1.0" encoding="UTF-8"?>'."\r\n";
	    $rss .= '<rss version="2.0">'."\r\n";
	    $rss .= '<channel>'."\r\n";
	    $rss .= '<title>Twit2RSS</title>'."\r\n";
	    $rss .= '<link>http://twitter.com</link>'."\r\n";
	    $rss .= '<image>http://s3.amazonaws.com/twitter_production/profile_images/24254342/twitter_bird_profile_normal.png</image>';
	    $rss .= '<description>Twit2RSS - Read Twitter via RSS.  By Whitley Media - www.whitleymedia.com</description>'."\r\n";

	    foreach($nodeList as $statuses)
	    {
	        $id = '';
	        $description = '';
	        $pubDate = '';
	        $text = '';
	        $image = '';
	        $name = '';
	        $screen_name = '';
	        $link = '';
	        $guid = '';
	        $source = '';
	        $category = '';
		  $wpDate = ''; 
		  $protected = '';
	        foreach($statuses->childNodes as $status)
	        {
	            switch ($status->nodeName)
	            {
	              case 'id':
	                    $id = $status->nodeValue;
	                    break;
	              case 'created_at':
	                    $pubDate = $status->nodeValue;
	                    $wpDate = date('Y-m-d g:i', strtotime($pubDate));
	                    $pubDate = date('D, d M Y g:i a e', strtotime($pubDate));
	                    break;
	              case 'protected':
	                    $protected = $status->nodeValue;
	                    break;
	              case 'text':
	                    $text = $status->nodeValue;
			  	  break;
		        case 'source':
	    	            $source = $status->nodeValue;
	    	            break;
	              case 'user':
                    	foreach($status->childNodes as $user)
	                  {
	                  	switch ($user->nodeName)
                          	{
                    			case 'profile_image_url':
                                		$image = $user->nodeValue;
                                		break;
                            		case 'screen_name':
                                		$screen_name = $user->nodeValue;
                                		break;
                            		case 'name':
                                		$name = $user->nodeValue;
                                		break;
                        	}
                  	}
                  	break;
            	}
        	 }

    		if(isset($_GET["jtl"]))
    		{
    			JTLCapture($id, $name, $screen_name,$image,$link,$text,$wpDate, $protected);
		}

           //Item       
          $rss .= '<item>';
 	    $rss .= '<title><![CDATA['.$text.']]></title>'."\r\n";
          $rss .= '<pubDate>'.$pubDate.'</pubDate>'."\r\n";
          $link = 'http://www.twitter.com/'.$screen_name.'/statuses/'.$id;
          $guid = $link;
          $rss .= '<link><![CDATA['.$link.']]></link>'."\r\n";
          $rss .= '<guid><![CDATA['.$guid.']]></guid>'."\r\n";
          $rss .= '<author>'.$name.'</author>';
          if(!empty($friends[$screen_name]))
          {
              $category = $friends[$screen_name];
          }
          $rss .= '<category>'.$category.'</category>';
          $rss .= '<description><![CDATA[<a href="http://www.twitter.com/'.$screen_name.'"><img alt="'.$name.'" src="'.$image.'" /></a> ';
          $rss .= '<strong><a href="http://www.twitter.com/'.$screen_name.'" title="'.$name.'">'.$screen_name.'</a></strong> ';
          $rss .= makeClickableLinks($text).' ';
          $rss .= '<a href="'.$link.'">'.$pubDate.'</a>';
          $rss .= ' from '.$source.' ';
          $rss .= '<p><a href="http://twitter.com/home?status=@'.urlencode($screen_name).'">Reply</a> ';
          $rss .= '| <a href="http://twitter.com/home?status=D '.urlencode($screen_name).'">Direct Message</a> ';
          $rss .= '| <a href="http://twitter.com/home?status=">Update Status</a>';
          $rss .= ']]></description>'."\r\n";
          $rss .= '</item>'."\r\n";
      }

      //End RSS
      $rss .= '</channel>'."\r\n".'</rss>'."\r\n";

      return $rss;
    }
}

function JTLInstall()
{
   global $wpdb;

   $table_name = $wpdb->prefix . "jtl_links";
   if($wpdb->get_var("show tables like '$table_name'") != $table_name) {
      
      $sql = "CREATE TABLE " . $table_name . " (
	  id bigint(20) NOT NULL,
        name varchar(255) NOT NULL,
	  screen_name varchar(255) NOT NULL,
	  image varchar(2000) NULL,
	  link varchar(2000) NULL,
	  status varchar(255) NULL,
        created_at datetime NOT NULL,
        protected varchar(5) NULL,
	  UNIQUE KEY id (id)
	);";

      if ( file_exists ( ABSPATH . 'wp-admin/includes/upgrade.php') )
      {
	      require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
      }
      if ( file_exists ( ABSPATH . 'wp-admin/upgrade.php') )
      {
	      require_once(ABSPATH . 'wp-admin/upgrade.php');
      }
      dbDelta($sql);
   }
}

function JTLCapture($id,$name, $screen_name,$image,$link,$text,$pubDate, $protected)
{
	global $wpdb;

      $link = findLink($text);
     
	if($link)
        {
	    $saved_id = $wpdb->get_var("select id from ".$wpdb->prefix."jtl_links where id=$id");
	    if (!$saved_id) {
	        $wpdb->query("insert into ".$wpdb->prefix . "jtl_links (id, name, screen_name, image, link, "
			."status, created_at, protected) values($id, '$name','$screen_name', '$image', '$link', '".$wpdb->Escape($text)."', '$pubDate', '$protected')");
	    }
	}
}


function findLink( $text ) {

   if(ereg('(((f|ht){1}tp://)[-a-zA-Z0-9@:%_\+.~#?&//=]+)', $text, $regs))
   {
	$fullurl = $regs[0];
   }

   return $fullurl;

}


function makeClickableLinks($text) { 

    $text = eregi_replace('(((f|ht){1}tp://)[-a-zA-Z0-9@:%_\+.~#?&//=]+)', 
    '<a href="\\1">\\1</a>', $text); 

    $text = eregi_replace('([[:space:]()[{}])(www.[-a-zA-Z0-9@:%_\+.~#?&//=]+)', 
    '\\1<a href="http://\\2">\\2</a>', $text); 

    $text = eregi_replace('([_\.0-9a-z-]+@([0-9a-z][0-9a-z-]+\.)+[a-z]{2,3})', 
    '<a href="mailto:\\1">\\1</a>', $text); 

    return $text; 

} 
 

/*
Sean Huber CURL library

This library is a basic implementation of CURL capabilities.
It works in most modern versions of IE and FF.

==================================== USAGE ====================================
It exports the CURL object globally, so set a callback with setCallback($func).
(Use setCallback(array('class_name', 'func_name')) to set a callback as a func
that lies within a different class)
Then use one of the CURL request methods:

get($url);
post($url, $vars); vars is a urlencoded string in query string format.

Your callback function will then be called with 1 argument, the response text.
If a callback is not defined, your request will return the response text.
*/

class CURL {
var $callback = false;
//Don't change the lines below.
//You only need to change the username/password at the top of the script.
public $username = '';
public $password = '';

function setCallback($func_name) {
$this->callback = $func_name;
}

function doRequest($method, $url, $vars) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_USERPWD,$this->username.':'.$this->password);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)");
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookie.txt');
curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookie.txt');
if ($method == 'POST') {
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $vars);
}
$data = curl_exec($ch);
curl_close($ch);
if ($data) {
if ($this->callback)
{
$callback = $this->callback;
$this->callback = false;
return call_user_func($callback, $data);
} else {
return $data;
}
} else {
return curl_error($ch);
}
}

function get($url) {
return $this->doRequest('GET', $url, 'NULL');
}

function post($url, $vars) {
return $this->doRequest('POST', $url, $vars);
}
}
?>